package com.junmeng.lib.ui.topview.core

import android.app.Activity
import android.app.Application
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.Window
import androidx.annotation.MainThread
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import com.junmeng.lib.ui.topview.R
import com.junmeng.lib.ui.topview.util.ViewUtil
import java.lang.ref.WeakReference

object WindowTopViewManager {
    interface Listener {
        /**
         * 当用户自定义视图被添加时
         * @param type String IViewFactory.getType
         * @param child View 被添加的用户自定义视图
         * @param viewFactory IViewFactory
         */
        fun onAdd(type: String, child: View, viewFactory: IViewFactory) = Unit

        /**
         * 当用户自定义视图被移除时
         * @param type String IViewFactory.getType
         * @param child View 被移除的用户自定义视图
         * @param viewFactory IViewFactory?
         * @return Unit
         */
        fun onRemove(type: String, child: View, viewFactory: IViewFactory?) = Unit

        /**
         * 首个activity创建时
         * @param firstActivity Activity
         */
        fun onFirstActivityCreated(firstActivity: Activity) = Unit
    }

    const val TAG = "TopViewManager"

    private var mCurrentActivity: WeakReference<Activity>? = null

    private var mViewFactoryMap = hashMapOf<String, IViewFactory>()

    private var mCacheHasApplyChildMap = hashMapOf<String, View>() //缓存已经被应用的ViewFactory产生的child

    private var mListenerList: MutableList<Listener> = mutableListOf()

    private var mActivityLifecycleCallbacks: Application.ActivityLifecycleCallbacks? = null

    private var mApplication: Application? = null

    private var mFirstActivityCreate = false


    /**
     * 初始化，使用其他方法前必先调用此
     * @param application Application
     * @return
     */
    fun init(application: Application): WindowTopViewManager {
        if (mApplication != null) {
            Log.i(TAG, "已经初始化了")
            return this
        }
        mApplication = application
        mActivityLifecycleCallbacks = object :
            SimpleActivityLifecycleCallbacks() {
            override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
                mCurrentActivity = WeakReference(activity)
                if (!mFirstActivityCreate) {
                    mFirstActivityCreate = true
                    mViewFactoryMap?.forEach {
                        it.value?.onFirstActivityCreated(activity)
                    }
                    mListenerList.forEach {
                        it.onFirstActivityCreated(activity)
                    }
                }
            }

            override fun onActivityResumed(activity: Activity) {
                Log.i(TAG, "onActivityResumed $activity")

                mCurrentActivity = WeakReference(activity)
                proxyWindowCallback(activity)
                mCacheHasApplyChildMap.map {
                    it.key
                }
                    .filter { type ->
                        //过滤掉哪些只应用在当前的
                        mViewFactoryMap[type]?.onlyApplyCurrent() != true
                    }
                    .forEach { type ->
                        applyViewFactory(type)
                    }

            }

            override fun onActivityDestroyed(activity: Activity) {
                Log.i(TAG, "onActivityDestroyed $activity")
                if (mCurrentActivity?.get() === activity) {
                    Log.i(TAG, "currentActivity clear ")
                    mCurrentActivity?.clear()
                }

                recoverWindowCallback(activity)
            }

        }
        application.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks)
        return this
    }

    /**
     * 释放资源
     * 用户确定不再使用其相关功能时可以调用此进行资源释放
     */
    fun uninit() {
        mActivityLifecycleCallbacks?.let {
            mApplication?.unregisterActivityLifecycleCallbacks(it)
        }
        mCurrentActivity?.clear()
        mViewFactoryMap.clear()
        mCacheHasApplyChildMap.clear()
        mListenerList.clear()
        mApplication = null
    }


    /**
     * 获得Application
     * @return Application?
     */
    fun getApplication(): Application? {
        return mApplication
    }

    /**
     * 添加监听器
     * @param listener Listener
     */
    fun addListener(listener: Listener) {
        mListenerList.add(listener)
    }

    fun addListener(lifecycleOwner: LifecycleOwner, listener: Listener) {
        addListener(lifecycleOwner.lifecycle, listener)
    }

    fun addListener(lifecycle: Lifecycle, listener: Listener) {
        addListener(listener)
        lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    lifecycle?.removeObserver(this)
                    removeListener(listener)
                }
            }

        })
    }

    /**
     * 移除监听器
     * @param listener Listener
     */
    fun removeListener(listener: Listener) {
        mListenerList.remove(listener)
    }

    private fun recoverWindowCallback(activity: Activity) {
        if (activity.window?.callback is WindowBackPressedCallback) {
            activity.window?.callback =
                (activity.window?.callback as WindowBackPressedCallback).originalCallback
        }
    }

    private fun proxyWindowCallback(activity: Activity) {
        val originalCallback: Window.Callback = activity.window.callback
        val globalCallback = WindowBackPressedCallback(originalCallback)
        globalCallback.addOnBackPressedListener(object :
            WindowBackPressedCallback.OnBackPressedListener {
            override fun onBackPressed(): Boolean {
                mViewFactoryMap.map {
                    it.value
                }.forEach {
                    if (it.onBackPressed()) {
                        return true //有人拦截了就退出foreach
                    }
                }

                return false
            }

        })

        activity.window.callback = globalCallback
    }

    /**
     * 添加视图工厂
     * @param viewFactory IViewFactory
     * @param replaceIfExist Boolean true--存在则替换 false--存在则忽略
     * @return com.junmeng.lib.floatcore.FloatingViewManager
     */
    @JvmOverloads
    fun registerViewFactory(
        viewFactory: IViewFactory,
        replaceIfExist: Boolean = true
    ): WindowTopViewManager {
        if (replaceIfExist) {
            mViewFactoryMap[viewFactory.getType()] = viewFactory
        } else {
            if (!mViewFactoryMap.containsKey(viewFactory.getType())) {
                mViewFactoryMap[viewFactory.getType()] = viewFactory
            }
        }
        return this
    }

    /**
     * 移除视图工厂
     * @param type String
     * @return com.junmeng.lib.floatcore.FloatingViewManager
     */
    fun unregisterViewFactory(type: String): WindowTopViewManager {
        mViewFactoryMap.remove(type)
        return this
    }

    /**
     * 获得指定的视图工厂
     * @param type String
     * @return IViewFactory?
     */

    fun getViewFactory(type: String): IViewFactory? {
        return mViewFactoryMap[type]
    }

    /**
     * 获得当前已经被添加的child视图
     * @param type String
     * @return View?
     */
    fun getHasAddedChildView(type: String): View? {
        return mCacheHasApplyChildMap[type]
    }


    /**
     * 添加指定类型的视图工厂的child视图
     * @param type String
     * @return Boolean
     */
    @MainThread
    fun applyViewFactory(type: String): Boolean {
        mViewFactoryMap[type]?.let { viewFactory ->
            mCurrentActivity?.get()?.let { activity ->
                if (!viewFactory.askIfAppliedOnTargetActivity(activity)) {
                    return false
                }
                getDecorView(activity)?.let { decorView ->
                    val parentView = viewFactory.getContainerView(decorView)
                    val child = mCacheHasApplyChildMap[type] ?: kotlin.run {
                        mApplication?.let { app ->
                            //由于此view会在activity切换之间来回添加移除，如果使用activity的话，在其onDestroy的时候可能出现一些异常情况
                            //例如RecyclerView附加在Activity A上，当A销毁时，RecyclerView的adapter会被置为null,导致界面不显示
                            viewFactory.onCreateView(parentView, LayoutInflater.from(app))
                        } ?: kotlin.run {

                            viewFactory.onCreateView(parentView, LayoutInflater.from(activity))
                        }
                    }
                    child.setTag(R.id.hijunmeng_topview_tag_priority, viewFactory.priority())
                    child.setTag(R.id.hijunmeng_topview_tag_flag, type)
                    mCacheHasApplyChildMap[type] = child

                    if (viewFactory.onlyApplyCurrent()) {
                        listenActivityDestroyEvent(activity, type)
                    }


                    //按优先级添加，值越大越靠近用户
                    addChildWithPriority(parentView, child, viewFactory.priority(), viewFactory)
                    return true
                } ?: kotlin.run {
                    Log.i(TAG, "decorView为null")
                }
            } ?: kotlin.run {
                Log.i(TAG, "currentActivity为null")
            }
        } ?: kotlin.run {
            Log.i(TAG, "未找到type=${type},请先注册后再使用")
        }
        return false
    }

    /**
     * 移除指定类型的视图
     * @param type String
     */
    fun unapplyViewFactory(type: String): Boolean {
        mCacheHasApplyChildMap[type]?.let { child ->
            if (child.parent is ViewGroup) {
                removeViewAndNotifyListener(child.parent as ViewGroup, child, type)
            }
            mCacheHasApplyChildMap.remove(type)
            getViewFactory(type)?.onDestroyView()
            return true
        }
        return false
    }

    /**
     * 暂时移除指定类型ViewFactory产生的child，在下次界面重新可见时仍然会添加child
     * 例如在当前界面调用此方法child视图会从父view移除，但退回桌面重新回到界面此child会重新被添加
     * @param type String
     */
    fun unapplyViewFactoryOnlyCurrent(type: String): Boolean {
        mCacheHasApplyChildMap[type]?.let { child ->
            if (child.parent is ViewGroup) {
                removeViewAndNotifyListener(child.parent as ViewGroup, child, type)
            }
            return true
        }
        return false
    }


    /**
     * 获得当前activity所在window的DecorView
     * @return ViewGroup?
     */
    fun getCurrentActivityDecorView(): ViewGroup? {
        return mCurrentActivity?.get()?.window?.decorView as ViewGroup?
    }

    /**
     * 获得当前activity
     * @return Activity?
     */
    fun getCurrentActivity(): Activity? {
        return mCurrentActivity?.get()
    }

    /**
     * 判断是否是添加到window的topview
     * @param view View
     * @return Boolean
     */
    fun isTopView(view: View): Boolean {
        val type = view.getTag(R.id.hijunmeng_topview_tag_flag) ?: return false
        return mViewFactoryMap.containsKey(type)
    }

    /**
     * 获得指定activity所在window的DecorView
     * @param activity Activity
     * @return ViewGroup?
     */
    private fun getDecorView(activity: Activity): ViewGroup? {
        return activity.window?.decorView as ViewGroup?
    }


    /**
     * 按优先级添加view 值越大越靠近用户
     * @param parentView ViewGroup
     * @param child View 要添加的子view
     * @param priority Int
     */
    @MainThread
    private fun addChildWithPriority(
        parentView: ViewGroup,
        child: View,
        priority: Int,
        viewFactory: IViewFactory
    ) {
        if (parentView.childCount < 1) {
            addViewAndNotifyListener(parentView, child, viewFactory)
        } else {
            var hasAdd = false

            var lstIndex = -1
            for (i in parentView.childCount - 1 downTo 0) {

                val tmp = parentView.getChildAt(i)
                if (tmp === child) { //说明child已经是parentView的子view
                    Log.i(TAG, "tmp === child")
                    hasAdd = true
                    continue
                }
                val pri = tmp?.getTag(R.id.hijunmeng_topview_tag_priority)
                if (pri is Int) {
                    lstIndex = i
                    if (priority >= pri) {
                        if (i == parentView.childCount - 1) {//直接加到末尾
                            addViewAndNotifyListener(parentView, child, viewFactory)
                        } else {
                            addViewAndNotifyListener(parentView, child, i + 1, viewFactory)
                        }

                        hasAdd = true
                        break
                    }
                }
            }
            if (!hasAdd) {
                addViewAndNotifyListener(parentView, child, lstIndex, viewFactory)
            }
        }
    }

    private fun removeViewAndNotifyListener(
        parent: ViewGroup,
        child: View,
        type: String
    ) {
        parent.removeView(child)
        mViewFactoryMap[type]?.let {
            it.onRemoveFromContainerView(parent, child)
        }
        mListenerList.forEach {
            it.onRemove(type, child, mViewFactoryMap[type])
        }
    }


    private fun addViewAndNotifyListener(
        parent: ViewGroup,
        child: View,
        viewFactory: IViewFactory
    ) {
        addViewAndNotifyListener(parent, child, -1, viewFactory)
    }

    private fun addViewAndNotifyListener(
        parent: ViewGroup,
        child: View,
        index: Int,
        viewFactory: IViewFactory
    ) {
        ViewUtil.addView(parent, child, index)
        viewFactory.onAddIntoContainerView(parent, child)
        mListenerList.forEach {
            it.onAdd(viewFactory.getType(), child, viewFactory)
        }
    }

    private fun listenActivityDestroyEvent(
        activity: Activity,
        type: String
    ) {
        if (activity is LifecycleOwner) {
            (activity as LifecycleOwner).lifecycle.addObserver(object :
                LifecycleEventObserver {
                override fun onStateChanged(
                    source: LifecycleOwner,
                    event: Lifecycle.Event
                ) {
                    if (event == Lifecycle.Event.ON_DESTROY) {
                        source.lifecycle.removeObserver(this)
                        unapplyViewFactory(type)
                    }
                }

            })
        }
    }


}

